home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / triv_lib / trivrais.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-20  |  12.8 KB  |  325 lines

  1. /******************************************************************************
  2. * TrivRais.c - Degree raising from trivariate functions.              *
  3. *******************************************************************************
  4. * Written by Gershon Elber, October 1994.                      *
  5. ******************************************************************************/
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "triv_loc.h"
  11.  
  12. /* Define some marcos to make some of the routines below look better. They  */
  13. /* calculate the index of U, V, W point of the control mesh in Points.        */
  14. #define RAISED_TV(U, V, W)    TRIV_MESH_UVW(RaisedTV, U, V, W)
  15. #define TV(U, V, W)        TRIV_MESH_UVW(TV, U, V, W)
  16.  
  17. /*****************************************************************************
  18. * DESCRIPTION:                                                               M
  19. * Returns a new trivariate representing the same curve as TV but with its    M
  20. * degree raised by one.                                 M
  21. *                                                                            *
  22. * PARAMETERS:                                                                M
  23. *   TV:       To raise its degree.                                           M
  24. *   Dir:       Direction of degree raising. Either U, V or W.             M
  25. *                                                                            *
  26. * RETURN VALUE:                                                              M
  27. *   TrivTVStruct *:  A surface with same geometry as TV but with one         M
  28. *                    degree higher.                                          M
  29. *                                                                            *
  30. * KEYWORDS:                                                                  M
  31. *   TrivTVDegreeRaise, degree raising                                        M
  32. *****************************************************************************/
  33. TrivTVStruct *TrivTVDegreeRaise(TrivTVStruct *TV, TrivTVDirType Dir)
  34. {
  35.     switch (TV -> GType) {
  36.     case TRIV_TVBEZIER_TYPE:
  37.         return TrivBzrTVDegreeRaise(TV, Dir);
  38.     case TRIV_TVBSPLINE_TYPE:
  39.         return TrivBspTVDegreeRaise(TV, Dir);
  40.     default:
  41.         TRIV_FATAL_ERROR(TRIV_ERR_UNDEF_GEOM);
  42.         return NULL;
  43.     }
  44. }
  45.  
  46. /*****************************************************************************
  47. * DESCRIPTION:                                                               M
  48. * Returns a new Bezier trivariate, identical to the original but with one    M
  49. * degree higher, in the requested direction Dir.                             M
  50. * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then:   M
  51. *               i        k-i                         V
  52. * Q(0) = P(0), Q(i) = --- P(i-1) + (---) P(i), Q(k) = P(k-1).             V
  53. *               k         k                         V
  54. * This is applied to all rows/cols of the trivariate.                 M
  55. *                                                                            *
  56. * PARAMETERS:                                                                M
  57. *   TV:        To raise it degree by one.                                    M
  58. *   Dir:       Direction of degree raising. Either U, V or W.             M
  59. *                                                                            *
  60. * RETURN VALUE:                                                              M
  61. *   TrivTVStruct *:  A surface with one degree higher in direction Dir,      M
  62. *                     representing the same geometry as TV.             M
  63. *                                                                            *
  64. * KEYWORDS:                                                                  M
  65. *   TrivBzrTVDegreeRaise, degree raising                                     M
  66. *****************************************************************************/
  67. TrivTVStruct *TrivBzrTVDegreeRaise(TrivTVStruct *TV, TrivTVDirType Dir)
  68. {
  69.     CagdBType
  70.     IsNotRational = !TRIV_IS_RATIONAL_TV(TV);
  71.     int i, j, k, l,
  72.     ULength = TV -> ULength,
  73.     VLength = TV -> VLength,
  74.     WLength = TV -> WLength,
  75.     MaxCoord = CAGD_NUM_OF_PT_COORD(TV -> PType);
  76.     TrivTVStruct
  77.     *RaisedTV = NULL;
  78.  
  79.     switch (Dir) {
  80.     case TRIV_CONST_U_DIR:
  81.         RaisedTV = TrivBzrTVNew(ULength + 1, VLength, WLength,
  82.                     TV -> PType);
  83.  
  84.         for (j = 0; j < VLength; j++)
  85.         for (k = 0; k < WLength; k++) {
  86.             for (l = IsNotRational; l <= MaxCoord; l++)        /* Q(0). */
  87.             RaisedTV -> Points[l][RAISED_TV(0, j, k)] =
  88.                 TV -> Points[l][TV(0, j, k)];
  89.  
  90.             for (i = 1; i < ULength; i++)            /* Q(i). */
  91.                 for (l = IsNotRational; l <= MaxCoord; l++)
  92.                 RaisedTV -> Points[l][RAISED_TV(i, j, k)] =
  93.                     TV -> Points[l][TV(i - 1, j, k)] *
  94.                                  (i / ((CagdRType) ULength)) +
  95.                     TV -> Points[l][TV(i, j, k)] *
  96.                      ((ULength - i) / ((CagdRType) ULength));
  97.  
  98.             for (l = IsNotRational; l <= MaxCoord; l++)        /* Q(k). */
  99.                 RaisedTV -> Points[l][RAISED_TV(ULength, j, k)] =
  100.                 TV -> Points[l][TV(ULength - 1, j, k)];
  101.         }
  102.         break;
  103.     case TRIV_CONST_V_DIR:
  104.         RaisedTV = TrivBzrTVNew(ULength, VLength + 1, WLength,
  105.                     TV -> PType);
  106.  
  107.         for (i = 0; i < ULength; i++)
  108.         for (k = 0; k < WLength; k++) {
  109.             for (l = IsNotRational; l <= MaxCoord; l++)        /* Q(0). */
  110.             RaisedTV -> Points[l][RAISED_TV(i, 0, k)] =
  111.                 TV -> Points[l][TV(i, 0, k)];
  112.  
  113.             for (j = 1; j < VLength; j++)            /* Q(i). */
  114.                 for (l = IsNotRational; l <= MaxCoord; l++)
  115.                 RaisedTV -> Points[l][RAISED_TV(i, j, k)] =
  116.                     TV -> Points[l][TV(i, j - 1, k)] *
  117.                                  (j / ((CagdRType) VLength)) +
  118.                     TV -> Points[l][TV(i, j, k)] *
  119.                      ((VLength - j) / ((CagdRType) VLength));
  120.  
  121.             for (l = IsNotRational; l <= MaxCoord; l++)        /* Q(k). */
  122.                 RaisedTV -> Points[l][RAISED_TV(i, VLength, k)] =
  123.                 TV -> Points[l][TV(i, VLength - 1, k)];
  124.         }
  125.         break;
  126.     case TRIV_CONST_W_DIR:
  127.         RaisedTV = TrivBzrTVNew(ULength, VLength, WLength + 1,
  128.                     TV -> PType);
  129.  
  130.         for (i = 0; i < ULength; i++)
  131.         for (j = 0; j < VLength; j++) {
  132.             for (l = IsNotRational; l <= MaxCoord; l++)        /* Q(0). */
  133.             RaisedTV -> Points[l][RAISED_TV(i, j, 0)] =
  134.                 TV -> Points[l][TV(i, j, 0)];
  135.  
  136.             for (k = 1; k < WLength; k++)            /* Q(i). */
  137.                 for (l = IsNotRational; l <= MaxCoord; l++)
  138.                 RaisedTV -> Points[l][RAISED_TV(i, j, k)] =
  139.                     TV -> Points[l][TV(i, j, k - 1)] *
  140.                                  (k / ((CagdRType) WLength)) +
  141.                     TV -> Points[l][TV(i, j, k)] *
  142.                      ((WLength - k) / ((CagdRType) WLength));
  143.  
  144.             for (l = IsNotRational; l <= MaxCoord; l++)        /* Q(k). */
  145.                 RaisedTV -> Points[l][RAISED_TV(i, j, WLength)] =
  146.                 TV -> Points[l][TV(i, j, WLength - 1)];
  147.         }
  148.         break;
  149.     default:
  150.         TRIV_FATAL_ERROR(TRIV_ERR_DIR_NOT_VALID);
  151.         break;
  152.     }
  153.  
  154.     return RaisedTV;
  155. }
  156.  
  157. /*****************************************************************************
  158. * DESCRIPTION:                                                               M
  159. * Returns a new Bspline surface, identical to the original but with one      M
  160. * degree higher, in the requested direction Dir.                             M
  161. *                                                                            *
  162. * PARAMETERS:                                                                M
  163. *   TV:        To raise it degree by one.                                    M
  164. *   Dir:       Direction of degree raising. Either U, V or W.             M
  165. *                                                                            *
  166. * RETURN VALUE:                                                              M
  167. *   TrivTVStruct *:  A trivariate with one degree higher in direction Dir,   M
  168. *                    representing the same geometry as TV.             M
  169. *                                                                            *
  170. * KEYWORDS:                                                                  M
  171. *   TrivBspTVDegreeRaise, degree raising                                     M
  172. *****************************************************************************/
  173. TrivTVStruct *TrivBspTVDegreeRaise(TrivTVStruct *TV, TrivTVDirType Dir)
  174. {
  175.     CagdBType
  176.     IsNotRational = !TRIV_IS_RATIONAL_TV(TV);
  177.     int i, i2, j, j2, k, k2, l, RaisedLen,
  178.         ULength = TV -> ULength,
  179.         VLength = TV -> VLength,
  180.         WLength = TV -> WLength,
  181.         UOrder = TV -> UOrder,
  182.         VOrder = TV -> VOrder,
  183.         WOrder = TV -> WOrder,
  184.     MaxCoord = CAGD_NUM_OF_PT_COORD(TV -> PType);
  185.     TrivTVStruct
  186.     *RaisedTV = NULL;
  187.  
  188.     /* If surface is linear, degree raising means basically to increase the  */
  189.     /* knot multiplicity of each segment by one and add a middle point for   */
  190.     /* each such segment.                             */
  191.  
  192.     switch (Dir) {
  193.     case TRIV_CONST_U_DIR:
  194.         if (UOrder > 2) {
  195.         TRIV_FATAL_ERROR(TRIV_ERR_WRONG_ORDER);
  196.         return NULL;
  197.         }
  198.  
  199.         RaisedLen = ULength * 2 - 1;
  200.         RaisedTV = TrivBspTVNew(RaisedLen, VLength, WLength,
  201.                     UOrder + 1, VOrder, WOrder,
  202.                     TV -> PType);
  203.  
  204.         /* Update the knot vectors. */
  205.         for (i = 0; i < 3; i++)
  206.         RaisedTV -> UKnotVector[i] = TV -> UKnotVector[0];
  207.         for (i = 2, j = 3; i < ULength; i++, j += 2)
  208.         RaisedTV -> UKnotVector[j] =
  209.             RaisedTV -> UKnotVector[j + 1] = 
  210.                 TV -> VKnotVector[i];
  211.         for (i = j; i < j + 3; i++)
  212.         RaisedTV -> UKnotVector[i] = TV -> UKnotVector[ULength];
  213.         CAGD_GEN_COPY(RaisedTV -> VKnotVector, TV -> VKnotVector,
  214.               sizeof(CagdRType) * (VLength + VOrder));
  215.         CAGD_GEN_COPY(RaisedTV -> WKnotVector, TV -> WKnotVector,
  216.               sizeof(CagdRType) * (WLength + WOrder));
  217.  
  218.         /* Update the mesh. */
  219.         for (k = 0; k < WLength; k++)
  220.         for (j = 0; j < VLength; j++) {
  221.             for (l = IsNotRational; l <= MaxCoord; l++)
  222.             RaisedTV -> Points[l][RAISED_TV(0, j, k)] =
  223.                 TV -> Points[l][TV(0, j, k)];
  224.  
  225.             for (i = 1, i2 = 1; i < ULength; i++, i2 += 2)
  226.                 for (l = IsNotRational; l <= MaxCoord; l++) {
  227.                 RaisedTV -> Points[l][RAISED_TV(i2, j, k)] =
  228.                 TV -> Points[l][TV(i - 1, j, k)] * 0.5 +
  229.                 TV -> Points[l][TV(i, j, k)] * 0.5;
  230.                 RaisedTV -> Points[l][RAISED_TV(i2 + 1, j, k)] =
  231.                     TV -> Points[l][TV(i, j, k)];
  232.             }
  233.         }
  234.         break;
  235.     case TRIV_CONST_V_DIR:
  236.         if (VOrder > 2) {
  237.         TRIV_FATAL_ERROR(TRIV_ERR_WRONG_ORDER);
  238.         return NULL;
  239.         }
  240.  
  241.         RaisedLen = VLength * 2 - 1;
  242.         RaisedTV = TrivBspTVNew(ULength, RaisedLen, WLength,
  243.                     UOrder, VOrder + 1, WOrder,
  244.                     TV -> PType);
  245.  
  246.         /* Update the knot vectors. */
  247.         CAGD_GEN_COPY(RaisedTV -> UKnotVector, TV -> UKnotVector,
  248.               sizeof(CagdRType) * (ULength + UOrder));
  249.         for (i = 0; i < 3; i++)
  250.         RaisedTV -> VKnotVector[i] = TV -> VKnotVector[0];
  251.         for (i = 2, j = 3; i < VLength; i++, j += 2)
  252.         RaisedTV -> VKnotVector[j] =
  253.             RaisedTV -> VKnotVector[j + 1] = 
  254.                 TV -> VKnotVector[i];
  255.         for (i = j; i < j + 3; i++)
  256.         RaisedTV -> VKnotVector[i] = TV -> VKnotVector[VLength];
  257.         CAGD_GEN_COPY(RaisedTV -> WKnotVector, TV -> WKnotVector,
  258.               sizeof(CagdRType) * (WLength + WOrder));
  259.  
  260.         /* Update the mesh. */
  261.         for (k = 0; k < WLength; k++)
  262.         for (i = 0; i < ULength; i++) {
  263.             for (l = IsNotRational; l <= MaxCoord; l++)
  264.             RaisedTV -> Points[l][RAISED_TV(i, 0, k)] =
  265.                 TV -> Points[l][TV(i, 0, k)];
  266.  
  267.             for (j = 1, j2 = 1; j < VLength; j++, j2 += 2)
  268.                 for (l = IsNotRational; l <= MaxCoord; l++) {
  269.                 RaisedTV -> Points[l][RAISED_TV(i, j2, k)] =
  270.                 TV -> Points[l][TV(i, j - 1, k)] * 0.5 +
  271.                 TV -> Points[l][TV(i, j, k)] * 0.5;
  272.                 RaisedTV -> Points[l][RAISED_TV(i, j2 + 1, k)] =
  273.                     TV -> Points[l][TV(i, j, k)];
  274.             }
  275.         }
  276.         break;
  277.     case TRIV_CONST_W_DIR:
  278.         if (WOrder > 2) {
  279.         TRIV_FATAL_ERROR(TRIV_ERR_WRONG_ORDER);
  280.         return NULL;
  281.         }
  282.  
  283.         RaisedLen = WLength * 2 - 1;
  284.         RaisedTV = TrivBspTVNew(ULength, VLength, RaisedLen,
  285.                     UOrder, VOrder, WOrder + 1,
  286.                     TV -> PType);
  287.  
  288.         /* Update the knot vectors. */
  289.         CAGD_GEN_COPY(RaisedTV -> UKnotVector, TV -> UKnotVector,
  290.               sizeof(CagdRType) * (ULength + UOrder));
  291.         CAGD_GEN_COPY(RaisedTV -> VKnotVector, TV -> VKnotVector,
  292.               sizeof(CagdRType) * (VLength + VOrder));
  293.         for (i = 0; i < 3; i++)
  294.         RaisedTV -> WKnotVector[i] = TV -> WKnotVector[0];
  295.         for (i = 2, j = 3; i < WLength; i++, j += 2)
  296.         RaisedTV -> WKnotVector[j] = RaisedTV -> WKnotVector[j + 1] = 
  297.             TV -> WKnotVector[i];
  298.         for (i = j; i < j + 3; i++)
  299.         RaisedTV -> WKnotVector[i] = TV -> WKnotVector[WLength];
  300.  
  301.         /* Update the mesh. */
  302.         for (j = 0; j < VLength; j++)
  303.         for (i = 0; i < ULength; i++) {
  304.             for (l = IsNotRational; l <= MaxCoord; l++)
  305.             RaisedTV -> Points[l][RAISED_TV(i, j, 0)] =
  306.                 TV -> Points[l][TV(i, j, 0)];
  307.  
  308.             for (k = 1, k2 = 1; k < WLength; k++, k2 += 2)
  309.                 for (l = IsNotRational; l <= MaxCoord; l++) {
  310.                 RaisedTV -> Points[l][RAISED_TV(i, j, k2)] =
  311.                 TV -> Points[l][TV(i, j, k - 1)] * 0.5 +
  312.                 TV -> Points[l][TV(i, j, k)] * 0.5;
  313.                 RaisedTV -> Points[l][RAISED_TV(i, j, k2 + 1)] =
  314.                     TV -> Points[l][TV(i, j, k)];
  315.             }
  316.         }
  317.         break;
  318.     default:
  319.         TRIV_FATAL_ERROR(TRIV_ERR_DIR_NOT_VALID);
  320.         break;
  321.     }
  322.  
  323.     return RaisedTV;
  324. }
  325.